/*********************************************************************
**	File: index.hpp
**	Author: Asteroth
**	Date: 24/03/2013
*********************************************************************/
#ifndef __DEFINES_HPP__
#define __DEFINES_HPP__

#include <vector>

#ifdef USE_RAW_POINTERS
	#define __ptr__(type) type*
	#define __isnull__(value) (value == NULL)
#else
	#define __ptr__(type) boost::shared_ptr<type>
	#define __isnull__(value) (value == NULL)
#endif

namespace std {

	template<typename value_type, typename index_type = long, bool reuseIndices = true>
	class index {
	private:
		std::vector<__ptr__(value_type)> elements;
		index_type unusedCount;
		index_type firstUnused;

	public:
		typedef index_type index_type;
		typedef value_type value_type;

		index(): unusedCount(0), firstUnused(-1) {}
		index(const index &other): elements(other.elements), unusedCount(other.unusedCount), firstUnused(other.firstUnused) {}

		index& operator = (const index &other) {
			elements = other.elements;
			unusedCount = other.unusedCount;
			firstUnused = other.firstUnused;
			return *this;
		}

		inline size_t size() { return elements.size() - unusedCount; }

		inline __ptr__(value_type) get(const index_type &index) { return elements[index]; }
		
		inline index_type insert(__ptr__(value_type) value) {
			index_type index;
			if (reuseIndices && unusedCount > 0) {
				index = firstUnused;
				elements[firstUnused] = value;
				unusedCount--;
				if (unusedCount == 0)
					firstUnused = -1;
				else
					while (firstUnused < 0 || !__isnull__(elements[firstUnused]))
						firstUnused++;
			} else {
				index = (index_type)elements.size();
				elements.push_back(value);
			}
			return index;
		}

		inline __ptr__(value_type) remove(const index_type &index) {
			__ptr__(value_type) value = elements[index];
			elements[index] = NULL;
			if (!__isnull__(value)) {
				if (reuseIndices && (firstUnused > index || firstUnused < 0))
					firstUnused = index;
				unusedCount++;
			}
			return value;
		}

	};

}

#undef __ptr__
#undef __isnull__

#endif
